import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { InjectQueue } from '@nestjs/bull';
import { Queue } from 'bull';
import { v4 as uuidv4 } from 'uuid';
import {
  NovelParseTask,
  TaskStatus,
  TaskType,
} from '../entities/novel-parse-task.entity';
import { NovelParseJobData } from '../processors/novel-parse.processor';

@Injectable()
export class NovelTaskService {
  private readonly logger = new Logger(NovelTaskService.name);

  constructor(
    @InjectRepository(NovelParseTask)
    private readonly taskRepository: Repository<NovelParseTask>,
    @InjectQueue('novel-parse')
    private readonly novelParseQueue: Queue,
  ) {}

  /**
   * 创建章节内容异步处理任务
   */
  async createChapterContentTask(
    novelId: number,
    originalUrl: string,
    novelTitle: string,
    platform: string,
  ): Promise<NovelParseTask> {
    // 幂等性检查：检查是否已有该小说的未完成任务
    const existingTask = await this.taskRepository.findOne({
      where: [
        {
          novelId,
          taskType: TaskType.CHAPTER_CONTENT,
          status: TaskStatus.PENDING,
        },
        {
          novelId,
          taskType: TaskType.CHAPTER_CONTENT,
          status: TaskStatus.PROCESSING,
        },
      ],
      order: { createdAt: 'DESC' },
    });

    if (existingTask) {
      this.logger.log(
        `小说 ${novelTitle} 已有未完成任务: ${existingTask.taskId}, 状态: ${existingTask.status}`,
      );

      // 检查是否是可能的服务重启导致的僵尸任务
      const now = new Date();
      if (
        existingTask.status === TaskStatus.PROCESSING &&
        existingTask.startedAt
      ) {
        const processingTime = now.getTime() - existingTask.startedAt.getTime();
        const isLikelyServiceRestart = processingTime > 2 * 60 * 1000; // 超过2分钟认为是重启

        if (isLikelyServiceRestart) {
          this.logger.warn(
            `检测到可能的服务重启，重置任务状态: ${existingTask.taskId}, 已处理: ${Math.round(processingTime / 1000)}秒`,
          );
          await this.taskRepository.update(existingTask.id, {
            status: TaskStatus.PENDING,
            errorMessage: '检测到服务重启，重新开始处理',
            startedAt: null, // 清除开始时间
            // 不增加重试次数
          });
        }
      }

      return existingTask;
    }

    const taskId = uuidv4();

    // 创建任务记录
    const task = this.taskRepository.create({
      taskId,
      taskType: TaskType.CHAPTER_CONTENT,
      novelId,
      novelTitle,
      originalUrl,
      status: TaskStatus.PENDING,
      taskData: {
        novelId,
        originalUrl,
        novelTitle,
        platform,
      },
    });

    await this.taskRepository.save(task);

    // 添加到队列
    const jobData: NovelParseJobData = {
      taskId,
      novelId,
      originalUrl,
      novelTitle,
      platform,
    };

    await this.novelParseQueue.add('chapter-content', jobData, {
      attempts: 3, // 最多重试3次
      backoff: {
        type: 'exponential',
        delay: 2000, // 初始延迟2秒
      },
      removeOnComplete: 10, // 保留最近10个完成的任务
      removeOnFail: 50, // 保留最近50个失败的任务
    });

    this.logger.log(`创建章节内容异步任务: ${taskId}, 小说ID: ${novelId}`);

    return task;
  }

  /**
   * 查询任务状态
   */
  async getTaskStatus(taskId: string): Promise<NovelParseTask | null> {
    const task = await this.taskRepository.findOne({
      where: { taskId },
    });

    if (!task) {
      this.logger.warn(`任务不存在: ${taskId}`);
      return null;
    }

    return task;
  }

  /**
   * 查询任务进度
   */
  async getTaskProgress(taskId: string): Promise<{
    status: TaskStatus;
    progress: number;
    totalChapters: number;
    processedChapters: number;
    successChapters: number;
    failedChapters: number;
    errorMessage?: string;
  } | null> {
    const task = await this.taskRepository.findOne({
      where: { taskId },
      select: [
        'status',
        'progress',
        'totalChapters',
        'processedChapters',
        'successChapters',
        'failedChapters',
        'errorMessage',
      ],
    });

    if (!task) {
      return null;
    }

    return {
      status: task.status,
      progress: task.progress,
      totalChapters: task.totalChapters,
      processedChapters: task.processedChapters,
      successChapters: task.successChapters,
      failedChapters: task.failedChapters,
      errorMessage: task.errorMessage || undefined,
    };
  }

  /**
   * 获取用户的任务列表
   */
  async getUserTasks(
    userId?: number,
    limit: number = 20,
    offset: number = 0,
  ): Promise<{ tasks: NovelParseTask[]; total: number }> {
    const queryBuilder = this.taskRepository
      .createQueryBuilder('task')
      .orderBy('task.createdAt', 'DESC')
      .take(limit)
      .skip(offset);

    // 如果指定了用户ID，可以添加用户过滤逻辑
    // 目前没有用户关联字段，暂时返回所有任务

    const [tasks, total] = await queryBuilder.getManyAndCount();

    return { tasks, total };
  }

  /**
   * 删除已完成的任务记录
   */
  async cleanCompletedTasks(daysOld: number = 7): Promise<number> {
    const cutoffDate = new Date();
    cutoffDate.setDate(cutoffDate.getDate() - daysOld);

    const result = await this.taskRepository
      .createQueryBuilder()
      .delete()
      .from(NovelParseTask)
      .where('status IN (:...statuses)', {
        statuses: [TaskStatus.COMPLETED, TaskStatus.FAILED],
      })
      .andWhere('createdAt < :cutoffDate', { cutoffDate })
      .execute();

    const deletedCount = result.affected || 0;
    this.logger.log(`清理了 ${deletedCount} 个过期任务记录`);

    return deletedCount;
  }

  /**
   * 重新执行失败的任务
   */
  async retryFailedTask(taskId: string): Promise<boolean> {
    const task = await this.taskRepository.findOne({
      where: { taskId },
    });

    if (!task) {
      return false;
    }

    if (task.status !== TaskStatus.FAILED) {
      this.logger.warn(`任务状态不是失败，无法重试: ${taskId}`);
      return false;
    }

    // 重置任务状态
    await this.taskRepository.update(taskId, {
      status: TaskStatus.PENDING,
      errorMessage: null,
      retryCount: task.retryCount + 1,
      nextRetryAt: null,
      startedAt: null,
      completedAt: null,
    });

    // 重新添加到队列
    const jobData: NovelParseJobData = {
      taskId,
      novelId: task.novelId!,
      originalUrl: task.originalUrl!,
      novelTitle: task.novelTitle!,
      platform: task.taskData?.platform || 'qidian',
    };

    await this.novelParseQueue.add('chapter-content', jobData, {
      attempts: 3,
      backoff: {
        type: 'exponential',
        delay: 2000,
      },
    });

    this.logger.log(`重新提交任务到队列: ${taskId}`);

    return true;
  }

  /**
   * 取消任务（仅限未开始的任务）
   */
  async cancelTask(taskId: string): Promise<boolean> {
    const task = await this.taskRepository.findOne({
      where: { taskId },
    });

    if (!task) {
      return false;
    }

    if (task.status !== TaskStatus.PENDING) {
      this.logger.warn(`任务已开始处理，无法取消: ${taskId}`);
      return false;
    }

    // 尝试从队列中移除任务
    const jobs = await this.novelParseQueue.getJobs(['waiting', 'delayed']);
    const targetJob = jobs.find((job) => job.data.taskId === taskId);

    if (targetJob) {
      await targetJob.remove();
    }

    // 更新任务状态
    await this.taskRepository.update(taskId, {
      status: TaskStatus.FAILED,
      errorMessage: '用户取消任务',
      completedAt: new Date(),
    });

    this.logger.log(`任务已取消: ${taskId}`);

    return true;
  }
}
